Loading the Data

library(readr)
There were 44 warnings (use warnings() to see them)
library(dplyr)

Attaching package: ‘dplyr’

The following object is masked _by_ ‘.GlobalEnv’:

    first

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ───────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.3     ✓ purrr   0.3.4
✓ tibble  3.0.5     ✓ stringr 1.4.0
✓ tidyr   1.1.2     ✓ forcats 0.5.1
── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(ggrepel)
library(ggplot2)
library(reshape2)

Attaching package: ‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths
epl_player = read_csv("playerstats_epl.csv")
Duplicated column names deduplicated: 'Progressive Distance' => 'Progressive Distance_1' [83], 'Touches' => 'Touches_1' [100]
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  Date = col_date(format = ""),
  Name = col_character(),
  Round = col_character(),
  Venue = col_character(),
  Result = col_character(),
  Squad = col_character(),
  Opponent = col_character(),
  Start = col_character(),
  Pos = col_character()
)
ℹ Use `spec()` for the full column specifications.
bundesliga_player = read_csv("playerstats_bundesliga.csv")
Duplicated column names deduplicated: 'Progressive Distance' => 'Progressive Distance_1' [83], 'Touches' => 'Touches_1' [100]
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  Date = col_date(format = ""),
  Name = col_character(),
  Round = col_character(),
  Venue = col_character(),
  Result = col_character(),
  Squad = col_character(),
  Opponent = col_character(),
  Start = col_character(),
  Pos = col_character()
)
ℹ Use `spec()` for the full column specifications.
ligue1_player = read_csv("playerstats_ligue1.csv")
Duplicated column names deduplicated: 'Progressive Distance' => 'Progressive Distance_1' [83], 'Touches' => 'Touches_1' [100]
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  Date = col_date(format = ""),
  Name = col_character(),
  Round = col_character(),
  Venue = col_character(),
  Result = col_character(),
  Squad = col_character(),
  Opponent = col_character(),
  Start = col_character(),
  Pos = col_character()
)
ℹ Use `spec()` for the full column specifications.
seriea_player = read_csv("playerstats_seriea.csv")
Duplicated column names deduplicated: 'Progressive Distance' => 'Progressive Distance_1' [83], 'Touches' => 'Touches_1' [100]
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  Date = col_character(),
  Name = col_character(),
  Round = col_character(),
  Venue = col_character(),
  Result = col_character(),
  Squad = col_character(),
  Opponent = col_character(),
  Start = col_character(),
  Pos = col_character()
)
ℹ Use `spec()` for the full column specifications.
laliga_player = read_csv("playerstats_laliga.csv")
Duplicated column names deduplicated: 'Progressive Distance' => 'Progressive Distance_1' [83], 'Touches' => 'Touches_1' [100]
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  Date = col_character(),
  Name = col_character(),
  Round = col_character(),
  Venue = col_character(),
  Result = col_character(),
  Squad = col_character(),
  Opponent = col_character(),
  Start = col_character(),
  Pos = col_character()
)
ℹ Use `spec()` for the full column specifications.
epl_player["Matchweek"] = 0
bundesliga_player["Matchweek"] = 0
ligue1_player["Matchweek"] = 0
seriea_player["Matchweek"] = 0
laliga_player["Matchweek"] = 0
epl_player

Data Cleaning & Expected Goal vs Goal Comparison

Step 1: Aggregate Expected Goal and Goal Values across all Domestic League Games (per 90) Step 2: Remove Players who played less than 900 minutes (or equivalent of 10 games) Step 3: Plot a graph of Expected Goals vs Goals (per 90) with a line intercept = 0 A point that lies on the line represents a player who scores the same number of goals as he is expected to based on the xG model.

epl_player_summary = epl_player %>%
                        group_by(Name) %>%
                        summarise(TotalMinutesPlayed = sum(Min), TotalExpectedGoals = sum(`Expected Goals`), TotalGoals =sum(Goals), PenaltyGoals = sum(`Penalty Kicks Made`), TotalAssists= sum(Assists), TotalExpectedAssists = sum(`Expected Assist`), TotalnPxG = sum(`Non-Penalty Expected Goals`))
epl_player_summary = epl_player_summary %>% filter(TotalMinutesPlayed >= 900)
epl_player_summary["PerformanceGoalScored"] = epl_player_summary["TotalGoals"] - epl_player_summary["TotalExpectedGoals"]
epl_player_summary["GoalsPer90"] = epl_player_summary["TotalGoals"]*(90/epl_player_summary["TotalMinutesPlayed"])
epl_player_summary["ExpectedGoalsPer90"] = epl_player_summary["TotalExpectedGoals"]*(90/epl_player_summary["TotalMinutesPlayed"])
epl_player_summary["NonPenaltyGoals"] = epl_player_summary["TotalGoals"] - epl_player_summary["PenaltyGoals"]
epl_player_summary["NonPenaltyGoalsPer90"] = epl_player_summary["NonPenaltyGoals"]*(90/epl_player_summary["TotalMinutesPlayed"])
epl_player_summary["nPxGPer90"] = epl_player_summary["TotalnPxG"]*(90/epl_player_summary["TotalMinutesPlayed"])
epl_player_summary["AssistsPer90"] = epl_player_summary["TotalAssists"]*(90/epl_player_summary["TotalMinutesPlayed"])
epl_player_summary["xAssistsPer90"] = epl_player_summary["TotalExpectedAssists"]*(90/epl_player_summary["TotalMinutesPlayed"])
epl_player_summary
NA

Plotting Expected Goals vs Actual Goal (per 90) including Penalties

ggplot(data = epl_player_summary, aes(ExpectedGoalsPer90, GoalsPer90, label = Name)) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 > GoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.1, nudge_y = -0.1, force  = 2, force_pull = 0) + geom_point(aes(color = cut(ExpectedGoalsPer90, c(-Inf, 0.5, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.1) +ylim(0,1.2) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 < GoalsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = 0.1, nudge_y = 0.1) + labs(col="xG per 90") + xlab("xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield EPL Players Goals per 90 min vs xG per 90 min")

Plotting Expected Goals vs Actual Goal (per 90) excluding Penalties

ggplot(data = epl_player_summary, aes(nPxGPer90, NonPenaltyGoalsPer90, label = Name)) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.45 & nPxGPer90 > NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.1, nudge_y = -0.1, force  = 2, force_pull = 0, size = 3) + geom_point(aes(color = cut(nPxGPer90, c(-Inf, 0.45, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.1) +ylim(0,1.2) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.45 & nPxGPer90 < NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = 0.1, nudge_y = 0.1, size = 3) + labs(col="npxG per 90") + xlab("Non-Penalty xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield EPL Players Goals per 90 min vs nPxG per 90 min")

Plotting Expected Assists vs Actual Assist

ggplot(data = epl_player_summary, aes(xAssistsPer90, AssistsPer90, label = Name)) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.25 & xAssistsPer90 > AssistsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.2, nudge_y = -0.1, force  = 5, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(xAssistsPer90, c(-Inf, 0.25, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,0.75) +ylim(0,0.75) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.25 & xAssistsPer90 < AssistsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = 0.2, nudge_y = 0, force  = 5, force_pull = 0, size=3, label.padding = 0.5) + labs(col="xAssists per 90") + xlab("xAssists per 90 Minutes") + ylab("Assists per 90 Minutes") + ggtitle("Plot of Outfield EPL Players Assists per 90 min vs xAssists per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

bundesliga_player_summary = bundesliga_player %>%
                        group_by(Name) %>%
                        summarise(TotalMinutesPlayed = sum(Min), TotalExpectedGoals = sum(`Expected Goals`), TotalGoals =sum(Goals), PenaltyGoals = sum(`Penalty Kicks Made`), TotalAssists= sum(Assists), TotalExpectedAssists = sum(`Expected Assist`), TotalnPxG = sum(`Non-Penalty Expected Goals`))
bundesliga_player_summary = bundesliga_player_summary %>% filter(TotalMinutesPlayed >= 900)
bundesliga_player_summary["PerformanceGoalScored"] = bundesliga_player_summary["TotalGoals"] - bundesliga_player_summary["TotalExpectedGoals"]
bundesliga_player_summary["GoalsPer90"] = bundesliga_player_summary["TotalGoals"]*(90/bundesliga_player_summary["TotalMinutesPlayed"])
bundesliga_player_summary["ExpectedGoalsPer90"] = bundesliga_player_summary["TotalExpectedGoals"]*(90/bundesliga_player_summary["TotalMinutesPlayed"])
bundesliga_player_summary["NonPenaltyGoals"] = bundesliga_player_summary["TotalGoals"] - bundesliga_player_summary["PenaltyGoals"]
bundesliga_player_summary["NonPenaltyGoalsPer90"] = bundesliga_player_summary["NonPenaltyGoals"]*(90/bundesliga_player_summary["TotalMinutesPlayed"])
bundesliga_player_summary["nPxGPer90"] = bundesliga_player_summary["TotalnPxG"]*(90/bundesliga_player_summary["TotalMinutesPlayed"])
bundesliga_player_summary["AssistsPer90"] = bundesliga_player_summary["TotalAssists"]*(90/bundesliga_player_summary["TotalMinutesPlayed"])
bundesliga_player_summary["xAssistsPer90"] = bundesliga_player_summary["TotalExpectedAssists"]*(90/bundesliga_player_summary["TotalMinutesPlayed"])
bundesliga_player_summary
NA

Plotting Expected Goals vs Actual Goal (per 90) including Penalties

ggplot(data = bundesliga_player_summary, aes(ExpectedGoalsPer90, GoalsPer90, label = Name)) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 > GoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.1, nudge_y = 0, force  = 2, force_pull = 0, size = 3) + geom_point(aes(color = cut(ExpectedGoalsPer90, c(-Inf, 0.5, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.6) +ylim(0,1.6) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 < GoalsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = 0.1, nudge_y = 0.1, size = 3) + labs(col="xG per 90") + xlab("xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield Bundesliga Players Goals per 90 min vs xG per 90 min")

Plotting Expected Goals vs Actual Goal (per 90) excluding Penalties

ggplot(data = bundesliga_player_summary, aes(nPxGPer90, NonPenaltyGoalsPer90, label = Name)) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.45 & nPxGPer90 > NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.3, nudge_y = -0.2, force  = 3, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(nPxGPer90, c(-Inf, 0.45, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.6) +ylim(0,1.6) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.45 & nPxGPer90 < NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, nudge_x = 0.1, nudge_y = 0.5, size=3, label.padding = 0.5, box.padding = 0.5) + labs(col="npxG per 90") + xlab("Non-Penalty xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield Bundesliga Players Goals per 90 min vs nPxG per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

Plotting Expected Assists vs Actual Assist

ggplot(data = bundesliga_player_summary, aes(xAssistsPer90, AssistsPer90, label = Name)) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.3 & xAssistsPer90 > AssistsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.2, nudge_y = -0.2, force  = 5, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(xAssistsPer90, c(-Inf, 0.3, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,0.75) +ylim(0,0.75) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.3 & xAssistsPer90 < AssistsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.5, nudge_x = 0.25, nudge_y = 0, force  = 5, force_pull = 0, size=3, label.padding = 0.5) + labs(col="xAssists per 90") + xlab("xAssists per 90 Minutes") + ylab("Assists per 90 Minutes") + ggtitle("Plot of Outfield Bundesliga Players Assists per 90 min vs xAssists per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

ligue1_player_summary = ligue1_player %>%
                        group_by(Name) %>%
                        summarise(TotalMinutesPlayed = sum(Min), TotalExpectedGoals = sum(`Expected Goals`), TotalGoals =sum(Goals), PenaltyGoals = sum(`Penalty Kicks Made`), TotalAssists= sum(Assists), TotalExpectedAssists = sum(`Expected Assist`), TotalnPxG = sum(`Non-Penalty Expected Goals`))
ligue1_player_summary = ligue1_player_summary %>% filter(TotalMinutesPlayed >= 900)
ligue1_player_summary["PerformanceGoalScored"] = ligue1_player_summary["TotalGoals"] - ligue1_player_summary["TotalExpectedGoals"]
ligue1_player_summary["GoalsPer90"] = ligue1_player_summary["TotalGoals"]*(90/ligue1_player_summary["TotalMinutesPlayed"])
ligue1_player_summary["ExpectedGoalsPer90"] = ligue1_player_summary["TotalExpectedGoals"]*(90/ligue1_player_summary["TotalMinutesPlayed"])
ligue1_player_summary["NonPenaltyGoals"] = ligue1_player_summary["TotalGoals"] - ligue1_player_summary["PenaltyGoals"]
ligue1_player_summary["NonPenaltyGoalsPer90"] = ligue1_player_summary["NonPenaltyGoals"]*(90/ligue1_player_summary["TotalMinutesPlayed"])
ligue1_player_summary["nPxGPer90"] = ligue1_player_summary["TotalnPxG"]*(90/ligue1_player_summary["TotalMinutesPlayed"])
ligue1_player_summary["AssistsPer90"] = ligue1_player_summary["TotalAssists"]*(90/ligue1_player_summary["TotalMinutesPlayed"])
ligue1_player_summary["xAssistsPer90"] = ligue1_player_summary["TotalExpectedAssists"]*(90/ligue1_player_summary["TotalMinutesPlayed"])
ligue1_player_summary
NA

Plotting Expected Goals vs Actual Goal (per 90) including Penalties

ggplot(data = ligue1_player_summary, aes(ExpectedGoalsPer90, GoalsPer90, label = Name)) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 > GoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.1, nudge_y = 0, force  = 2, force_pull = 0, size = 3) + geom_point(aes(color = cut(ExpectedGoalsPer90, c(-Inf, 0.5, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.2) +ylim(0,1.2) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 < GoalsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = -0.3, nudge_y = 0, size = 3) + labs(col="xG per 90") + xlab("xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield Ligue 1 Players Goals per 90 min vs xG per 90 min")

Plotting Expected Goals vs Actual Goal (per 90) excluding Penalties

ggplot(data = ligue1_player_summary, aes(nPxGPer90, NonPenaltyGoalsPer90, label = Name)) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.45 & nPxGPer90 > NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.3, nudge_y = -0.2, force  = 3, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(nPxGPer90, c(-Inf, 0.45, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.6) +ylim(0,1.6) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.45 & nPxGPer90 < NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, nudge_x = 0.1, nudge_y = 0.5, size=3, label.padding = 0.5, box.padding = 0.5) + labs(col="npxG per 90") + xlab("Non-Penalty xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield Ligue 1 Players Goals per 90 min vs nPxG per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

Plotting Expected Assists vs Actual Assist

ggplot(data = ligue1_player_summary, aes(xAssistsPer90, AssistsPer90, label = Name)) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.3 & xAssistsPer90 > AssistsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.2, nudge_y = -0.2, force  = 5, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(xAssistsPer90, c(-Inf, 0.3, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1) +ylim(0,1) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.3 & xAssistsPer90 < AssistsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.5, nudge_x = 0.25, nudge_y = 0, force  = 5, force_pull = 0, size=3, label.padding = 0.5) + labs(col="xAssists per 90") + xlab("xAssists per 90 Minutes") + ylab("Assists per 90 Minutes") + ggtitle("Plot of Outfield Ligue 1 Players Assists per 90 min vs xAssists per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

seriea_player_summary = seriea_player %>%
                        group_by(Name) %>%
                        summarise(TotalMinutesPlayed = sum(Min), TotalExpectedGoals = sum(`Expected Goals`), TotalGoals =sum(Goals), PenaltyGoals = sum(`Penalty Kicks Made`), TotalAssists= sum(Assists), TotalExpectedAssists = sum(`Expected Assist`), TotalnPxG = sum(`Non-Penalty Expected Goals`))
seriea_player_summary = seriea_player_summary %>% filter(TotalMinutesPlayed >= 900)
seriea_player_summary["PerformanceGoalScored"] = seriea_player_summary["TotalGoals"] - seriea_player_summary["TotalExpectedGoals"]
seriea_player_summary["GoalsPer90"] = seriea_player_summary["TotalGoals"]*(90/seriea_player_summary["TotalMinutesPlayed"])
seriea_player_summary["ExpectedGoalsPer90"] = seriea_player_summary["TotalExpectedGoals"]*(90/seriea_player_summary["TotalMinutesPlayed"])
seriea_player_summary["NonPenaltyGoals"] = seriea_player_summary["TotalGoals"] - seriea_player_summary["PenaltyGoals"]
seriea_player_summary["NonPenaltyGoalsPer90"] = seriea_player_summary["NonPenaltyGoals"]*(90/seriea_player_summary["TotalMinutesPlayed"])
seriea_player_summary["nPxGPer90"] = seriea_player_summary["TotalnPxG"]*(90/seriea_player_summary["TotalMinutesPlayed"])
seriea_player_summary["AssistsPer90"] = seriea_player_summary["TotalAssists"]*(90/seriea_player_summary["TotalMinutesPlayed"])
seriea_player_summary["xAssistsPer90"] = seriea_player_summary["TotalExpectedAssists"]*(90/seriea_player_summary["TotalMinutesPlayed"])
seriea_player_summary
NA

Plotting Expected Goals vs Actual Goal (per 90) including Penalties

ggplot(data = seriea_player_summary, aes(ExpectedGoalsPer90, GoalsPer90, label = Name)) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.6 & ExpectedGoalsPer90 > GoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.1, nudge_y = 0, force  = 2, force_pull = 0, size = 3) + geom_point(aes(color = cut(ExpectedGoalsPer90, c(-Inf, 0.6, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.5) +ylim(0,1.5) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.6 & ExpectedGoalsPer90 < GoalsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = -0.3, nudge_y = 0, size = 3) + labs(col="xG per 90") + xlab("xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield Serie A Players Goals per 90 min vs xG per 90 min")

Plotting Expected Goals vs Actual Goal (per 90) excluding Penalties

ggplot(data = seriea_player_summary, aes(nPxGPer90, NonPenaltyGoalsPer90, label = Name)) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.5 & nPxGPer90 > NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.3, nudge_y = -0.2, force  = 3, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(nPxGPer90, c(-Inf, 0.5, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.5) +ylim(0,1.5) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.5 & nPxGPer90 < NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, nudge_x = 0.1, nudge_y = 0.5, size=3, label.padding = 0.5, box.padding = 0.5) + labs(col="npxG per 90") + xlab("Non-Penalty xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield Serie A Players Goals per 90 min vs nPxG per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

Plotting Expected Assists vs Actual Assist

ggplot(data = seriea_player_summary, aes(xAssistsPer90, AssistsPer90, label = Name)) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.3 & xAssistsPer90 > AssistsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.2, nudge_y =0, force  = 5, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(xAssistsPer90, c(-Inf, 0.3, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1) +ylim(0,1) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.3 & xAssistsPer90 < AssistsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.5, nudge_x = 0.25, nudge_y = 0, force  = 5, force_pull = 0, size=3, label.padding = 0.5) + labs(col="xAssists per 90") + xlab("xAssists per 90 Minutes") + ylab("Assists per 90 Minutes") + ggtitle("Plot of Outfield Serie A Players Assists per 90 min vs xAssists per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

laliga_player_summary = laliga_player %>%
                        group_by(Name) %>%
                        summarise(TotalMinutesPlayed = sum(Min), TotalExpectedGoals = sum(`Expected Goals`), TotalGoals =sum(Goals), PenaltyGoals = sum(`Penalty Kicks Made`), TotalAssists= sum(Assists), TotalExpectedAssists = sum(`Expected Assist`), TotalnPxG = sum(`Non-Penalty Expected Goals`))
laliga_player_summary = laliga_player_summary %>% filter(TotalMinutesPlayed >= 900)
laliga_player_summary["PerformanceGoalScored"] = laliga_player_summary["TotalGoals"] - laliga_player_summary["TotalExpectedGoals"]
laliga_player_summary["GoalsPer90"] = laliga_player_summary["TotalGoals"]*(90/laliga_player_summary["TotalMinutesPlayed"])
laliga_player_summary["ExpectedGoalsPer90"] = laliga_player_summary["TotalExpectedGoals"]*(90/laliga_player_summary["TotalMinutesPlayed"])
laliga_player_summary["NonPenaltyGoals"] = laliga_player_summary["TotalGoals"] - laliga_player_summary["PenaltyGoals"]
laliga_player_summary["NonPenaltyGoalsPer90"] = laliga_player_summary["NonPenaltyGoals"]*(90/laliga_player_summary["TotalMinutesPlayed"])
laliga_player_summary["nPxGPer90"] = laliga_player_summary["TotalnPxG"]*(90/laliga_player_summary["TotalMinutesPlayed"])
laliga_player_summary["AssistsPer90"] = laliga_player_summary["TotalAssists"]*(90/laliga_player_summary["TotalMinutesPlayed"])
laliga_player_summary["xAssistsPer90"] = laliga_player_summary["TotalExpectedAssists"]*(90/laliga_player_summary["TotalMinutesPlayed"])
laliga_player_summary
NA

Plotting Expected Goals vs Actual Goal (per 90) including Penalties

ggplot(data = laliga_player_summary, aes(ExpectedGoalsPer90, GoalsPer90, label = Name)) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 > GoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.1, nudge_y = 0, force  = 2, force_pull = 0, size = 3) + geom_point(aes(color = cut(ExpectedGoalsPer90, c(-Inf, 0.5, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1.0) +ylim(0,1.0) + geom_text_repel(aes(x = ExpectedGoalsPer90, y = GoalsPer90, label = ifelse(ExpectedGoalsPer90 > 0.5 & ExpectedGoalsPer90 < GoalsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.1, nudge_x = -0.3, nudge_y = 0, size = 3) + labs(col="xG per 90") + xlab("xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield La Liga Players Goals per 90 min vs xG per 90 min")

Plotting Expected Goals vs Actual Goal (per 90) excluding Penalties

ggplot(data = laliga_player_summary, aes(nPxGPer90, NonPenaltyGoalsPer90, label = Name)) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.4 & nPxGPer90 > NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.3, nudge_y =0, force  = 3, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(nPxGPer90, c(-Inf, 0.4, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1) +ylim(0,1) + geom_text_repel(aes(x = nPxGPer90, y = NonPenaltyGoalsPer90, label = ifelse(nPxGPer90 > 0.4 & nPxGPer90 < NonPenaltyGoalsPer90, as.character(Name),'')), max.overlaps = 10, nudge_x = 0.1, nudge_y = 0, size=3, label.padding = 0.5, box.padding = 0.5) + labs(col="npxG per 90") + xlab("Non-Penalty xG per 90 Minutes") + ylab("Goals per 90 Minutes") + ggtitle("Plot of Outfield La Liga Players Goals per 90 min vs nPxG per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding

Plotting Expected Assists vs Actual Assist

ggplot(data = laliga_player_summary, aes(xAssistsPer90, AssistsPer90, label = Name)) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.25 & xAssistsPer90 > AssistsPer90, as.character(Name),'')), max.overlaps = 10, point.padding = 0.1, nudge_x = 0.2, nudge_y =0, force  = 5, force_pull = 0, size=3, label.padding = 0.5, box.padding = 0.5) + geom_point(aes(color = cut(xAssistsPer90, c(-Inf, 0.25, Inf)))) +geom_abline(intercept = 0, slope = 1, color = "orange") +xlim(0,1) +ylim(0,1) + geom_text_repel(aes(x = xAssistsPer90, y = AssistsPer90, label = ifelse(xAssistsPer90 > 0.25 & xAssistsPer90 < AssistsPer90, as.character(Name),'')), max.overlaps = 10, box.padding = 0.5, nudge_x = 0.25, nudge_y = 0.1, force  = 5, force_pull = 0, size=3, label.padding = 0.5) + labs(col="xAssists per 90") + xlab("xAssists per 90 Minutes") + ylab("Assists per 90 Minutes") + ggtitle("Plot of Outfield La Liga Players Assists per 90 min vs xAssists per 90 min")
Ignoring unknown parameters: label.paddingIgnoring unknown parameters: label.padding


get_pass_chart=function(name) {
  player = epl_player[which(epl_player["Name"] == name),]%>%
  select(Matchweek, Round,Opponent, Min, `Total Passes Completed`, `Total Passes Attempted`, `Short Passes Completed`, `Short Passes Attempted`,`Medium Passes Completed`, `Medium Passes Attempted`,`Long Passes Completed`,`Long Passes Attempted`)
  for (i in 1:38) {
    currmw = paste("Matchweek", toString(i), sep=" ")
    if (!any(player==currmw) ) {
      new_row = data.frame(i, currmw,"NA", 0, 0, 0, 0, 0, 0, 0, 0, 0)
      names(new_row) = c("Matchweek","Round", "Opponent", "Min", "Total Passes Completed", "Total Passes Attempted", "Short Passes Completed", "Short Passes Attempted", "Medium Passes Completed", "Medium Passes Attempted", "Long Passes Completed", "Long Passes Attempted")
      player = rbind(player, new_row)
    } else {
      player$Matchweek[player$Round == currmw] = i
    }
  }
  player = player[order(player$Matchweek),]
  
  temp_player <- melt(player[,c('Matchweek','Short Passes Attempted','Medium Passes Attempted','Long Passes Attempted')],id.vars = 1)
  
  title_value = paste(name, "Pass Chart", sep=" ")
  ggplot(temp_player,aes(x = Matchweek,y = value)) + 
    geom_bar(aes(fill = variable),stat = "identity",position = "dodge") +
    ggtitle(title_value) + 
    labs(col="Types of Passes")
  
}
get_pass_chart("Thiago Alcántara")


get_pressure_chart=function(name) {
  player = epl_player[which(epl_player["Name"] == name),]%>%
  select(Matchweek, Round,Opponent, Min, `Number of times applying pressures in Defensive third`, `Number of times applying pressures in Midfield third`, `Number of times applying pressures in Attacking third`)
  for (i in 1:38) {
    currmw = paste("Matchweek", toString(i), sep=" ")
    if (!any(player==currmw) ) {
      new_row = data.frame(i, currmw,"NA", 0, 0, 0, 0)
      names(new_row) = c("Matchweek","Round", "Opponent", "Min", "Number of times applying pressures in Defensive third", "Number of times applying pressures in Midfield third", "Number of times applying pressures in Attacking third")
      player = rbind(player, new_row)
    } else {
      player$Matchweek[player$Round == currmw] = i
    }
  }
  player = player[order(player$Matchweek),]
  colnames(player)[5] = "Defensive3rd"
  colnames(player)[6] = "Midfield3rd"
  colnames(player)[7] = "Attacking3rd"
  temp_player <- melt(player[,c('Matchweek','Defensive3rd','Midfield3rd','Attacking3rd')],id.vars = 1, value.name = "Pressures", variable.name = "Types of Pressure")
  title_value = paste(name, "Pressure Applied Chart", sep=" ")
  ggplot(temp_player,aes(x = Matchweek,y = Pressures)) +
    geom_bar(aes(fill = `Types of Pressure`),stat = "identity",position = "dodge") +
    ggtitle(title_value) +
    ylim(0, 30)
  
}
# get_pressure_chart("Thiago Alcántara")
get_pressure_chart("Trent Alexander-Arnold")

get_pressure_chart("Andrew Robertson")

get_pressure_chart("Mohamed Salah")

get_pressure_chart("Sadio Mané")

# get_pressure_chart("Roberto Firmino")
# get_pressure_chart("Fabinho")
# get_pressure_chart("Georginio Wijnaldum")
# get_pressure_chart("Bruno Fernandes")
# get_pressure_chart("Marcus Rashford")
# get_pressure_chart("Paul Pogba")
# get_pressure_chart("Scott McTominay")
# get_pressure_chart("Fred")
# get_pressure_chart("Edinson Cavani")
# get_pressure_chart("İlkay Gündoğan")
# get_pressure_chart("Kevin De Bruyne")
# get_pressure_chart("Riyad Mahrez")
# get_pressure_chart("Phil Foden")
# get_pressure_chart("Raheem Sterling")
# get_pressure_chart("Rodri")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKTG9hZGluZyB0aGUgRGF0YQoKYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyZXNoYXBlMikKCmVwbF9wbGF5ZXIgPSByZWFkX2NzdigicGxheWVyc3RhdHNfZXBsLmNzdiIpCmJ1bmRlc2xpZ2FfcGxheWVyID0gcmVhZF9jc3YoInBsYXllcnN0YXRzX2J1bmRlc2xpZ2EuY3N2IikKbGlndWUxX3BsYXllciA9IHJlYWRfY3N2KCJwbGF5ZXJzdGF0c19saWd1ZTEuY3N2IikKc2VyaWVhX3BsYXllciA9IHJlYWRfY3N2KCJwbGF5ZXJzdGF0c19zZXJpZWEuY3N2IikKbGFsaWdhX3BsYXllciA9IHJlYWRfY3N2KCJwbGF5ZXJzdGF0c19sYWxpZ2EuY3N2IikKCmVwbF9wbGF5ZXJbIk1hdGNod2VlayJdID0gMApidW5kZXNsaWdhX3BsYXllclsiTWF0Y2h3ZWVrIl0gPSAwCmxpZ3VlMV9wbGF5ZXJbIk1hdGNod2VlayJdID0gMApzZXJpZWFfcGxheWVyWyJNYXRjaHdlZWsiXSA9IDAKbGFsaWdhX3BsYXllclsiTWF0Y2h3ZWVrIl0gPSAwCmVwbF9wbGF5ZXIKYGBgCgoKRGF0YSBDbGVhbmluZyAmIEV4cGVjdGVkIEdvYWwgdnMgR29hbCBDb21wYXJpc29uCgpTdGVwIDE6IEFnZ3JlZ2F0ZSBFeHBlY3RlZCBHb2FsIGFuZCBHb2FsIFZhbHVlcyBhY3Jvc3MgYWxsIERvbWVzdGljIExlYWd1ZSBHYW1lcyAocGVyIDkwKQpTdGVwIDI6IFJlbW92ZSBQbGF5ZXJzIHdobyBwbGF5ZWQgbGVzcyB0aGFuIDkwMCBtaW51dGVzIChvciBlcXVpdmFsZW50IG9mIDEwIGdhbWVzKQpTdGVwIDM6IFBsb3QgYSBncmFwaCBvZiBFeHBlY3RlZCBHb2FscyB2cyBHb2FscyAocGVyIDkwKSB3aXRoIGEgbGluZSBpbnRlcmNlcHQgPSAwCkEgcG9pbnQgdGhhdCBsaWVzIG9uIHRoZSBsaW5lIHJlcHJlc2VudHMgYSBwbGF5ZXIgd2hvIHNjb3JlcyB0aGUgc2FtZSBudW1iZXIgb2YgZ29hbHMgYXMgaGUgaXMgZXhwZWN0ZWQgdG8gYmFzZWQgb24gdGhlIHhHIG1vZGVsLgoKYGBge3J9CmVwbF9wbGF5ZXJfc3VtbWFyeSA9IGVwbF9wbGF5ZXIgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KE5hbWUpICU+JQogICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoVG90YWxNaW51dGVzUGxheWVkID0gc3VtKE1pbiksIFRvdGFsRXhwZWN0ZWRHb2FscyA9IHN1bShgRXhwZWN0ZWQgR29hbHNgKSwgVG90YWxHb2FscyA9c3VtKEdvYWxzKSwgUGVuYWx0eUdvYWxzID0gc3VtKGBQZW5hbHR5IEtpY2tzIE1hZGVgKSwgVG90YWxBc3Npc3RzPSBzdW0oQXNzaXN0cyksIFRvdGFsRXhwZWN0ZWRBc3Npc3RzID0gc3VtKGBFeHBlY3RlZCBBc3Npc3RgKSwgVG90YWxuUHhHID0gc3VtKGBOb24tUGVuYWx0eSBFeHBlY3RlZCBHb2Fsc2ApKQplcGxfcGxheWVyX3N1bW1hcnkgPSBlcGxfcGxheWVyX3N1bW1hcnkgJT4lIGZpbHRlcihUb3RhbE1pbnV0ZXNQbGF5ZWQgPj0gOTAwKQplcGxfcGxheWVyX3N1bW1hcnlbIlBlcmZvcm1hbmNlR29hbFNjb3JlZCJdID0gZXBsX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEdvYWxzIl0gLSBlcGxfcGxheWVyX3N1bW1hcnlbIlRvdGFsRXhwZWN0ZWRHb2FscyJdCmVwbF9wbGF5ZXJfc3VtbWFyeVsiR29hbHNQZXI5MCJdID0gZXBsX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEdvYWxzIl0qKDkwL2VwbF9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmVwbF9wbGF5ZXJfc3VtbWFyeVsiRXhwZWN0ZWRHb2Fsc1BlcjkwIl0gPSBlcGxfcGxheWVyX3N1bW1hcnlbIlRvdGFsRXhwZWN0ZWRHb2FscyJdKig5MC9lcGxfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQplcGxfcGxheWVyX3N1bW1hcnlbIk5vblBlbmFsdHlHb2FscyJdID0gZXBsX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEdvYWxzIl0gLSBlcGxfcGxheWVyX3N1bW1hcnlbIlBlbmFsdHlHb2FscyJdCmVwbF9wbGF5ZXJfc3VtbWFyeVsiTm9uUGVuYWx0eUdvYWxzUGVyOTAiXSA9IGVwbF9wbGF5ZXJfc3VtbWFyeVsiTm9uUGVuYWx0eUdvYWxzIl0qKDkwL2VwbF9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmVwbF9wbGF5ZXJfc3VtbWFyeVsiblB4R1BlcjkwIl0gPSBlcGxfcGxheWVyX3N1bW1hcnlbIlRvdGFsblB4RyJdKig5MC9lcGxfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQplcGxfcGxheWVyX3N1bW1hcnlbIkFzc2lzdHNQZXI5MCJdID0gZXBsX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEFzc2lzdHMiXSooOTAvZXBsX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKZXBsX3BsYXllcl9zdW1tYXJ5WyJ4QXNzaXN0c1BlcjkwIl0gPSBlcGxfcGxheWVyX3N1bW1hcnlbIlRvdGFsRXhwZWN0ZWRBc3Npc3RzIl0qKDkwL2VwbF9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmVwbF9wbGF5ZXJfc3VtbWFyeQoKYGBgCgoKUGxvdHRpbmcgRXhwZWN0ZWQgR29hbHMgdnMgQWN0dWFsIEdvYWwgKHBlciA5MCkgaW5jbHVkaW5nIFBlbmFsdGllcwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBlcGxfcGxheWVyX3N1bW1hcnksIGFlcyhFeHBlY3RlZEdvYWxzUGVyOTAsIEdvYWxzUGVyOTAsIGxhYmVsID0gTmFtZSkpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gRXhwZWN0ZWRHb2Fsc1BlcjkwLCB5ID0gR29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoRXhwZWN0ZWRHb2Fsc1BlcjkwID4gMC41ICYgRXhwZWN0ZWRHb2Fsc1BlcjkwID4gR29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBwb2ludC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4xLCBudWRnZV95ID0gLTAuMSwgZm9yY2UgID0gMiwgZm9yY2VfcHVsbCA9IDApICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjdXQoRXhwZWN0ZWRHb2Fsc1BlcjkwLCBjKC1JbmYsIDAuNSwgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDEuMSkgK3lsaW0oMCwxLjIpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gRXhwZWN0ZWRHb2Fsc1BlcjkwLCB5ID0gR29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoRXhwZWN0ZWRHb2Fsc1BlcjkwID4gMC41ICYgRXhwZWN0ZWRHb2Fsc1BlcjkwIDwgR29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBib3gucGFkZGluZyA9IDAuMSwgbnVkZ2VfeCA9IDAuMSwgbnVkZ2VfeSA9IDAuMSkgKyBsYWJzKGNvbD0ieEcgcGVyIDkwIikgKyB4bGFiKCJ4RyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiR29hbHMgcGVyIDkwIE1pbnV0ZXMiKSArIGdndGl0bGUoIlBsb3Qgb2YgT3V0ZmllbGQgRVBMIFBsYXllcnMgR29hbHMgcGVyIDkwIG1pbiB2cyB4RyBwZXIgOTAgbWluIikKYGBgCgpQbG90dGluZyBFeHBlY3RlZCBHb2FscyB2cyBBY3R1YWwgR29hbCAocGVyIDkwKSBleGNsdWRpbmcgUGVuYWx0aWVzCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGVwbF9wbGF5ZXJfc3VtbWFyeSwgYWVzKG5QeEdQZXI5MCwgTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gTmFtZSkpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gblB4R1BlcjkwLCB5ID0gTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKG5QeEdQZXI5MCA+IDAuNDUgJiBuUHhHUGVyOTAgPiBOb25QZW5hbHR5R29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBwb2ludC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4xLCBudWRnZV95ID0gLTAuMSwgZm9yY2UgID0gMiwgZm9yY2VfcHVsbCA9IDAsIHNpemUgPSAzKSArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY3V0KG5QeEdQZXI5MCwgYygtSW5mLCAwLjQ1LCBJbmYpKSkpICtnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yID0gIm9yYW5nZSIpICt4bGltKDAsMS4xKSAreWxpbSgwLDEuMikgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSBuUHhHUGVyOTAsIHkgPSBOb25QZW5hbHR5R29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoblB4R1BlcjkwID4gMC40NSAmIG5QeEdQZXI5MCA8IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIGJveC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4xLCBudWRnZV95ID0gMC4xLCBzaXplID0gMykgKyBsYWJzKGNvbD0ibnB4RyBwZXIgOTAiKSArIHhsYWIoIk5vbi1QZW5hbHR5IHhHIHBlciA5MCBNaW51dGVzIikgKyB5bGFiKCJHb2FscyBwZXIgOTAgTWludXRlcyIpICsgZ2d0aXRsZSgiUGxvdCBvZiBPdXRmaWVsZCBFUEwgUGxheWVycyBHb2FscyBwZXIgOTAgbWluIHZzIG5QeEcgcGVyIDkwIG1pbiIpCmBgYAoKUGxvdHRpbmcgRXhwZWN0ZWQgQXNzaXN0cyB2cyBBY3R1YWwgQXNzaXN0CgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBlcGxfcGxheWVyX3N1bW1hcnksIGFlcyh4QXNzaXN0c1BlcjkwLCBBc3Npc3RzUGVyOTAsIGxhYmVsID0gTmFtZSkpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0geEFzc2lzdHNQZXI5MCwgeSA9IEFzc2lzdHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoeEFzc2lzdHNQZXI5MCA+IDAuMjUgJiB4QXNzaXN0c1BlcjkwID4gQXNzaXN0c1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjIsIG51ZGdlX3kgPSAtMC4xLCBmb3JjZSAgPSA1LCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41LCBib3gucGFkZGluZyA9IDAuNSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGN1dCh4QXNzaXN0c1BlcjkwLCBjKC1JbmYsIDAuMjUsIEluZikpKSkgK2dlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgY29sb3IgPSAib3JhbmdlIikgK3hsaW0oMCwwLjc1KSAreWxpbSgwLDAuNzUpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0geEFzc2lzdHNQZXI5MCwgeSA9IEFzc2lzdHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoeEFzc2lzdHNQZXI5MCA+IDAuMjUgJiB4QXNzaXN0c1BlcjkwIDwgQXNzaXN0c1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIGJveC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4yLCBudWRnZV95ID0gMCwgZm9yY2UgID0gNSwgZm9yY2VfcHVsbCA9IDAsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSkgKyBsYWJzKGNvbD0ieEFzc2lzdHMgcGVyIDkwIikgKyB4bGFiKCJ4QXNzaXN0cyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiQXNzaXN0cyBwZXIgOTAgTWludXRlcyIpICsgZ2d0aXRsZSgiUGxvdCBvZiBPdXRmaWVsZCBFUEwgUGxheWVycyBBc3Npc3RzIHBlciA5MCBtaW4gdnMgeEFzc2lzdHMgcGVyIDkwIG1pbiIpCmBgYAoKCmBgYHtyfQpidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5ID0gYnVuZGVzbGlnYV9wbGF5ZXIgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KE5hbWUpICU+JQogICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoVG90YWxNaW51dGVzUGxheWVkID0gc3VtKE1pbiksIFRvdGFsRXhwZWN0ZWRHb2FscyA9IHN1bShgRXhwZWN0ZWQgR29hbHNgKSwgVG90YWxHb2FscyA9c3VtKEdvYWxzKSwgUGVuYWx0eUdvYWxzID0gc3VtKGBQZW5hbHR5IEtpY2tzIE1hZGVgKSwgVG90YWxBc3Npc3RzPSBzdW0oQXNzaXN0cyksIFRvdGFsRXhwZWN0ZWRBc3Npc3RzID0gc3VtKGBFeHBlY3RlZCBBc3Npc3RgKSwgVG90YWxuUHhHID0gc3VtKGBOb24tUGVuYWx0eSBFeHBlY3RlZCBHb2Fsc2ApKQpidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5ID0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeSAlPiUgZmlsdGVyKFRvdGFsTWludXRlc1BsYXllZCA+PSA5MDApCmJ1bmRlc2xpZ2FfcGxheWVyX3N1bW1hcnlbIlBlcmZvcm1hbmNlR29hbFNjb3JlZCJdID0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxHb2FscyJdIC0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxFeHBlY3RlZEdvYWxzIl0KYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiR29hbHNQZXI5MCJdID0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxHb2FscyJdKig5MC9idW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiRXhwZWN0ZWRHb2Fsc1BlcjkwIl0gPSBidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEV4cGVjdGVkR29hbHMiXSooOTAvYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmJ1bmRlc2xpZ2FfcGxheWVyX3N1bW1hcnlbIk5vblBlbmFsdHlHb2FscyJdID0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxHb2FscyJdIC0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiUGVuYWx0eUdvYWxzIl0KYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiTm9uUGVuYWx0eUdvYWxzUGVyOTAiXSA9IGJ1bmRlc2xpZ2FfcGxheWVyX3N1bW1hcnlbIk5vblBlbmFsdHlHb2FscyJdKig5MC9idW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiblB4R1BlcjkwIl0gPSBidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbG5QeEciXSooOTAvYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmJ1bmRlc2xpZ2FfcGxheWVyX3N1bW1hcnlbIkFzc2lzdHNQZXI5MCJdID0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxBc3Npc3RzIl0qKDkwL2J1bmRlc2xpZ2FfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJ4QXNzaXN0c1BlcjkwIl0gPSBidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEV4cGVjdGVkQXNzaXN0cyJdKig5MC9idW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeQoKYGBgCgoKUGxvdHRpbmcgRXhwZWN0ZWQgR29hbHMgdnMgQWN0dWFsIEdvYWwgKHBlciA5MCkgaW5jbHVkaW5nIFBlbmFsdGllcwoKYGBge3J9CmdncGxvdChkYXRhID0gYnVuZGVzbGlnYV9wbGF5ZXJfc3VtbWFyeSwgYWVzKEV4cGVjdGVkR29hbHNQZXI5MCwgR29hbHNQZXI5MCwgbGFiZWwgPSBOYW1lKSkgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSBFeHBlY3RlZEdvYWxzUGVyOTAsIHkgPSBHb2Fsc1BlcjkwLCBsYWJlbCA9IGlmZWxzZShFeHBlY3RlZEdvYWxzUGVyOTAgPiAwLjUgJiBFeHBlY3RlZEdvYWxzUGVyOTAgPiBHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjEsIG51ZGdlX3kgPSAwLCBmb3JjZSAgPSAyLCBmb3JjZV9wdWxsID0gMCwgc2l6ZSA9IDMpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjdXQoRXhwZWN0ZWRHb2Fsc1BlcjkwLCBjKC1JbmYsIDAuNSwgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDEuNikgK3lsaW0oMCwxLjYpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gRXhwZWN0ZWRHb2Fsc1BlcjkwLCB5ID0gR29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoRXhwZWN0ZWRHb2Fsc1BlcjkwID4gMC41ICYgRXhwZWN0ZWRHb2Fsc1BlcjkwIDwgR29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBib3gucGFkZGluZyA9IDAuMSwgbnVkZ2VfeCA9IDAuMSwgbnVkZ2VfeSA9IDAuMSwgc2l6ZSA9IDMpICsgbGFicyhjb2w9InhHIHBlciA5MCIpICsgeGxhYigieEcgcGVyIDkwIE1pbnV0ZXMiKSArIHlsYWIoIkdvYWxzIHBlciA5MCBNaW51dGVzIikgKyBnZ3RpdGxlKCJQbG90IG9mIE91dGZpZWxkIEJ1bmRlc2xpZ2EgUGxheWVycyBHb2FscyBwZXIgOTAgbWluIHZzIHhHIHBlciA5MCBtaW4iKQpgYGAKCgpQbG90dGluZyBFeHBlY3RlZCBHb2FscyB2cyBBY3R1YWwgR29hbCAocGVyIDkwKSBleGNsdWRpbmcgUGVuYWx0aWVzCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGJ1bmRlc2xpZ2FfcGxheWVyX3N1bW1hcnksIGFlcyhuUHhHUGVyOTAsIE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBsYWJlbCA9IE5hbWUpKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IG5QeEdQZXI5MCwgeSA9IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBsYWJlbCA9IGlmZWxzZShuUHhHUGVyOTAgPiAwLjQ1ICYgblB4R1BlcjkwID4gTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGFzLmNoYXJhY3RlcihOYW1lKSwnJykpLCBtYXgub3ZlcmxhcHMgPSAxMCwgcG9pbnQucGFkZGluZyA9IDAuMSwgbnVkZ2VfeCA9IDAuMywgbnVkZ2VfeSA9IC0wLjIsIGZvcmNlICA9IDMsIGZvcmNlX3B1bGwgPSAwLCBzaXplPTMsIGxhYmVsLnBhZGRpbmcgPSAwLjUsIGJveC5wYWRkaW5nID0gMC41KSArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY3V0KG5QeEdQZXI5MCwgYygtSW5mLCAwLjQ1LCBJbmYpKSkpICtnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yID0gIm9yYW5nZSIpICt4bGltKDAsMS42KSAreWxpbSgwLDEuNikgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSBuUHhHUGVyOTAsIHkgPSBOb25QZW5hbHR5R29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoblB4R1BlcjkwID4gMC40NSAmIG5QeEdQZXI5MCA8IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIG51ZGdlX3ggPSAwLjEsIG51ZGdlX3kgPSAwLjUsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSwgYm94LnBhZGRpbmcgPSAwLjUpICsgbGFicyhjb2w9Im5weEcgcGVyIDkwIikgKyB4bGFiKCJOb24tUGVuYWx0eSB4RyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiR29hbHMgcGVyIDkwIE1pbnV0ZXMiKSArIGdndGl0bGUoIlBsb3Qgb2YgT3V0ZmllbGQgQnVuZGVzbGlnYSBQbGF5ZXJzIEdvYWxzIHBlciA5MCBtaW4gdnMgblB4RyBwZXIgOTAgbWluIikKYGBgCgoKUGxvdHRpbmcgRXhwZWN0ZWQgQXNzaXN0cyB2cyBBY3R1YWwgQXNzaXN0CgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBidW5kZXNsaWdhX3BsYXllcl9zdW1tYXJ5LCBhZXMoeEFzc2lzdHNQZXI5MCwgQXNzaXN0c1BlcjkwLCBsYWJlbCA9IE5hbWUpKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IHhBc3Npc3RzUGVyOTAsIHkgPSBBc3Npc3RzUGVyOTAsIGxhYmVsID0gaWZlbHNlKHhBc3Npc3RzUGVyOTAgPiAwLjMgJiB4QXNzaXN0c1BlcjkwID4gQXNzaXN0c1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjIsIG51ZGdlX3kgPSAtMC4yLCBmb3JjZSAgPSA1LCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41LCBib3gucGFkZGluZyA9IDAuNSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGN1dCh4QXNzaXN0c1BlcjkwLCBjKC1JbmYsIDAuMywgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDAuNzUpICt5bGltKDAsMC43NSkgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSB4QXNzaXN0c1BlcjkwLCB5ID0gQXNzaXN0c1BlcjkwLCBsYWJlbCA9IGlmZWxzZSh4QXNzaXN0c1BlcjkwID4gMC4zICYgeEFzc2lzdHNQZXI5MCA8IEFzc2lzdHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBib3gucGFkZGluZyA9IDAuNSwgbnVkZ2VfeCA9IDAuMjUsIG51ZGdlX3kgPSAwLCBmb3JjZSAgPSA1LCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41KSArIGxhYnMoY29sPSJ4QXNzaXN0cyBwZXIgOTAiKSArIHhsYWIoInhBc3Npc3RzIHBlciA5MCBNaW51dGVzIikgKyB5bGFiKCJBc3Npc3RzIHBlciA5MCBNaW51dGVzIikgKyBnZ3RpdGxlKCJQbG90IG9mIE91dGZpZWxkIEJ1bmRlc2xpZ2EgUGxheWVycyBBc3Npc3RzIHBlciA5MCBtaW4gdnMgeEFzc2lzdHMgcGVyIDkwIG1pbiIpCmBgYAoKCmBgYHtyfQpsaWd1ZTFfcGxheWVyX3N1bW1hcnkgPSBsaWd1ZTFfcGxheWVyICU+JQogICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShOYW1lKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKFRvdGFsTWludXRlc1BsYXllZCA9IHN1bShNaW4pLCBUb3RhbEV4cGVjdGVkR29hbHMgPSBzdW0oYEV4cGVjdGVkIEdvYWxzYCksIFRvdGFsR29hbHMgPXN1bShHb2FscyksIFBlbmFsdHlHb2FscyA9IHN1bShgUGVuYWx0eSBLaWNrcyBNYWRlYCksIFRvdGFsQXNzaXN0cz0gc3VtKEFzc2lzdHMpLCBUb3RhbEV4cGVjdGVkQXNzaXN0cyA9IHN1bShgRXhwZWN0ZWQgQXNzaXN0YCksIFRvdGFsblB4RyA9IHN1bShgTm9uLVBlbmFsdHkgRXhwZWN0ZWQgR29hbHNgKSkKbGlndWUxX3BsYXllcl9zdW1tYXJ5ID0gbGlndWUxX3BsYXllcl9zdW1tYXJ5ICU+JSBmaWx0ZXIoVG90YWxNaW51dGVzUGxheWVkID49IDkwMCkKbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJQZXJmb3JtYW5jZUdvYWxTY29yZWQiXSA9IGxpZ3VlMV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxHb2FscyJdIC0gbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEV4cGVjdGVkR29hbHMiXQpsaWd1ZTFfcGxheWVyX3N1bW1hcnlbIkdvYWxzUGVyOTAiXSA9IGxpZ3VlMV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxHb2FscyJdKig5MC9saWd1ZTFfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpsaWd1ZTFfcGxheWVyX3N1bW1hcnlbIkV4cGVjdGVkR29hbHNQZXI5MCJdID0gbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEV4cGVjdGVkR29hbHMiXSooOTAvbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJOb25QZW5hbHR5R29hbHMiXSA9IGxpZ3VlMV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxHb2FscyJdIC0gbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJQZW5hbHR5R29hbHMiXQpsaWd1ZTFfcGxheWVyX3N1bW1hcnlbIk5vblBlbmFsdHlHb2Fsc1BlcjkwIl0gPSBsaWd1ZTFfcGxheWVyX3N1bW1hcnlbIk5vblBlbmFsdHlHb2FscyJdKig5MC9saWd1ZTFfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpsaWd1ZTFfcGxheWVyX3N1bW1hcnlbIm5QeEdQZXI5MCJdID0gbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJUb3RhbG5QeEciXSooOTAvbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJBc3Npc3RzUGVyOTAiXSA9IGxpZ3VlMV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxBc3Npc3RzIl0qKDkwL2xpZ3VlMV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmxpZ3VlMV9wbGF5ZXJfc3VtbWFyeVsieEFzc2lzdHNQZXI5MCJdID0gbGlndWUxX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEV4cGVjdGVkQXNzaXN0cyJdKig5MC9saWd1ZTFfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpsaWd1ZTFfcGxheWVyX3N1bW1hcnkKCmBgYAoKClBsb3R0aW5nIEV4cGVjdGVkIEdvYWxzIHZzIEFjdHVhbCBHb2FsIChwZXIgOTApIGluY2x1ZGluZyBQZW5hbHRpZXMKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGxpZ3VlMV9wbGF5ZXJfc3VtbWFyeSwgYWVzKEV4cGVjdGVkR29hbHNQZXI5MCwgR29hbHNQZXI5MCwgbGFiZWwgPSBOYW1lKSkgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSBFeHBlY3RlZEdvYWxzUGVyOTAsIHkgPSBHb2Fsc1BlcjkwLCBsYWJlbCA9IGlmZWxzZShFeHBlY3RlZEdvYWxzUGVyOTAgPiAwLjUgJiBFeHBlY3RlZEdvYWxzUGVyOTAgPiBHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjEsIG51ZGdlX3kgPSAwLCBmb3JjZSAgPSAyLCBmb3JjZV9wdWxsID0gMCwgc2l6ZSA9IDMpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjdXQoRXhwZWN0ZWRHb2Fsc1BlcjkwLCBjKC1JbmYsIDAuNSwgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDEuMikgK3lsaW0oMCwxLjIpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gRXhwZWN0ZWRHb2Fsc1BlcjkwLCB5ID0gR29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoRXhwZWN0ZWRHb2Fsc1BlcjkwID4gMC41ICYgRXhwZWN0ZWRHb2Fsc1BlcjkwIDwgR29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBib3gucGFkZGluZyA9IDAuMSwgbnVkZ2VfeCA9IC0wLjMsIG51ZGdlX3kgPSAwLCBzaXplID0gMykgKyBsYWJzKGNvbD0ieEcgcGVyIDkwIikgKyB4bGFiKCJ4RyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiR29hbHMgcGVyIDkwIE1pbnV0ZXMiKSArIGdndGl0bGUoIlBsb3Qgb2YgT3V0ZmllbGQgTGlndWUgMSBQbGF5ZXJzIEdvYWxzIHBlciA5MCBtaW4gdnMgeEcgcGVyIDkwIG1pbiIpCmBgYAoKClBsb3R0aW5nIEV4cGVjdGVkIEdvYWxzIHZzIEFjdHVhbCBHb2FsIChwZXIgOTApIGV4Y2x1ZGluZyBQZW5hbHRpZXMKYGBge3J9CmdncGxvdChkYXRhID0gbGlndWUxX3BsYXllcl9zdW1tYXJ5LCBhZXMoblB4R1BlcjkwLCBOb25QZW5hbHR5R29hbHNQZXI5MCwgbGFiZWwgPSBOYW1lKSkgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSBuUHhHUGVyOTAsIHkgPSBOb25QZW5hbHR5R29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoblB4R1BlcjkwID4gMC40NSAmIG5QeEdQZXI5MCA+IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjMsIG51ZGdlX3kgPSAtMC4yLCBmb3JjZSAgPSAzLCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41LCBib3gucGFkZGluZyA9IDAuNSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGN1dChuUHhHUGVyOTAsIGMoLUluZiwgMC40NSwgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDEuNikgK3lsaW0oMCwxLjYpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gblB4R1BlcjkwLCB5ID0gTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKG5QeEdQZXI5MCA+IDAuNDUgJiBuUHhHUGVyOTAgPCBOb25QZW5hbHR5R29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBudWRnZV94ID0gMC4xLCBudWRnZV95ID0gMC41LCBzaXplPTMsIGxhYmVsLnBhZGRpbmcgPSAwLjUsIGJveC5wYWRkaW5nID0gMC41KSArIGxhYnMoY29sPSJucHhHIHBlciA5MCIpICsgeGxhYigiTm9uLVBlbmFsdHkgeEcgcGVyIDkwIE1pbnV0ZXMiKSArIHlsYWIoIkdvYWxzIHBlciA5MCBNaW51dGVzIikgKyBnZ3RpdGxlKCJQbG90IG9mIE91dGZpZWxkIExpZ3VlIDEgUGxheWVycyBHb2FscyBwZXIgOTAgbWluIHZzIG5QeEcgcGVyIDkwIG1pbiIpCmBgYAoKClBsb3R0aW5nIEV4cGVjdGVkIEFzc2lzdHMgdnMgQWN0dWFsIEFzc2lzdAoKYGBge3J9CmdncGxvdChkYXRhID0gbGlndWUxX3BsYXllcl9zdW1tYXJ5LCBhZXMoeEFzc2lzdHNQZXI5MCwgQXNzaXN0c1BlcjkwLCBsYWJlbCA9IE5hbWUpKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IHhBc3Npc3RzUGVyOTAsIHkgPSBBc3Npc3RzUGVyOTAsIGxhYmVsID0gaWZlbHNlKHhBc3Npc3RzUGVyOTAgPiAwLjMgJiB4QXNzaXN0c1BlcjkwID4gQXNzaXN0c1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjIsIG51ZGdlX3kgPSAtMC4yLCBmb3JjZSAgPSA1LCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41LCBib3gucGFkZGluZyA9IDAuNSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGN1dCh4QXNzaXN0c1BlcjkwLCBjKC1JbmYsIDAuMywgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDEpICt5bGltKDAsMSkgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSB4QXNzaXN0c1BlcjkwLCB5ID0gQXNzaXN0c1BlcjkwLCBsYWJlbCA9IGlmZWxzZSh4QXNzaXN0c1BlcjkwID4gMC4zICYgeEFzc2lzdHNQZXI5MCA8IEFzc2lzdHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBib3gucGFkZGluZyA9IDAuNSwgbnVkZ2VfeCA9IDAuMjUsIG51ZGdlX3kgPSAwLCBmb3JjZSAgPSA1LCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41KSArIGxhYnMoY29sPSJ4QXNzaXN0cyBwZXIgOTAiKSArIHhsYWIoInhBc3Npc3RzIHBlciA5MCBNaW51dGVzIikgKyB5bGFiKCJBc3Npc3RzIHBlciA5MCBNaW51dGVzIikgKyBnZ3RpdGxlKCJQbG90IG9mIE91dGZpZWxkIExpZ3VlIDEgUGxheWVycyBBc3Npc3RzIHBlciA5MCBtaW4gdnMgeEFzc2lzdHMgcGVyIDkwIG1pbiIpCmBgYAoKYGBge3J9CnNlcmllYV9wbGF5ZXJfc3VtbWFyeSA9IHNlcmllYV9wbGF5ZXIgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KE5hbWUpICU+JQogICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoVG90YWxNaW51dGVzUGxheWVkID0gc3VtKE1pbiksIFRvdGFsRXhwZWN0ZWRHb2FscyA9IHN1bShgRXhwZWN0ZWQgR29hbHNgKSwgVG90YWxHb2FscyA9c3VtKEdvYWxzKSwgUGVuYWx0eUdvYWxzID0gc3VtKGBQZW5hbHR5IEtpY2tzIE1hZGVgKSwgVG90YWxBc3Npc3RzPSBzdW0oQXNzaXN0cyksIFRvdGFsRXhwZWN0ZWRBc3Npc3RzID0gc3VtKGBFeHBlY3RlZCBBc3Npc3RgKSwgVG90YWxuUHhHID0gc3VtKGBOb24tUGVuYWx0eSBFeHBlY3RlZCBHb2Fsc2ApKQpzZXJpZWFfcGxheWVyX3N1bW1hcnkgPSBzZXJpZWFfcGxheWVyX3N1bW1hcnkgJT4lIGZpbHRlcihUb3RhbE1pbnV0ZXNQbGF5ZWQgPj0gOTAwKQpzZXJpZWFfcGxheWVyX3N1bW1hcnlbIlBlcmZvcm1hbmNlR29hbFNjb3JlZCJdID0gc2VyaWVhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEdvYWxzIl0gLSBzZXJpZWFfcGxheWVyX3N1bW1hcnlbIlRvdGFsRXhwZWN0ZWRHb2FscyJdCnNlcmllYV9wbGF5ZXJfc3VtbWFyeVsiR29hbHNQZXI5MCJdID0gc2VyaWVhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEdvYWxzIl0qKDkwL3NlcmllYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCnNlcmllYV9wbGF5ZXJfc3VtbWFyeVsiRXhwZWN0ZWRHb2Fsc1BlcjkwIl0gPSBzZXJpZWFfcGxheWVyX3N1bW1hcnlbIlRvdGFsRXhwZWN0ZWRHb2FscyJdKig5MC9zZXJpZWFfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpzZXJpZWFfcGxheWVyX3N1bW1hcnlbIk5vblBlbmFsdHlHb2FscyJdID0gc2VyaWVhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEdvYWxzIl0gLSBzZXJpZWFfcGxheWVyX3N1bW1hcnlbIlBlbmFsdHlHb2FscyJdCnNlcmllYV9wbGF5ZXJfc3VtbWFyeVsiTm9uUGVuYWx0eUdvYWxzUGVyOTAiXSA9IHNlcmllYV9wbGF5ZXJfc3VtbWFyeVsiTm9uUGVuYWx0eUdvYWxzIl0qKDkwL3NlcmllYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCnNlcmllYV9wbGF5ZXJfc3VtbWFyeVsiblB4R1BlcjkwIl0gPSBzZXJpZWFfcGxheWVyX3N1bW1hcnlbIlRvdGFsblB4RyJdKig5MC9zZXJpZWFfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpzZXJpZWFfcGxheWVyX3N1bW1hcnlbIkFzc2lzdHNQZXI5MCJdID0gc2VyaWVhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbEFzc2lzdHMiXSooOTAvc2VyaWVhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKc2VyaWVhX3BsYXllcl9zdW1tYXJ5WyJ4QXNzaXN0c1BlcjkwIl0gPSBzZXJpZWFfcGxheWVyX3N1bW1hcnlbIlRvdGFsRXhwZWN0ZWRBc3Npc3RzIl0qKDkwL3NlcmllYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCnNlcmllYV9wbGF5ZXJfc3VtbWFyeQoKYGBgCgoKUGxvdHRpbmcgRXhwZWN0ZWQgR29hbHMgdnMgQWN0dWFsIEdvYWwgKHBlciA5MCkgaW5jbHVkaW5nIFBlbmFsdGllcwoKYGBge3J9CmdncGxvdChkYXRhID0gc2VyaWVhX3BsYXllcl9zdW1tYXJ5LCBhZXMoRXhwZWN0ZWRHb2Fsc1BlcjkwLCBHb2Fsc1BlcjkwLCBsYWJlbCA9IE5hbWUpKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IEV4cGVjdGVkR29hbHNQZXI5MCwgeSA9IEdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKEV4cGVjdGVkR29hbHNQZXI5MCA+IDAuNiAmIEV4cGVjdGVkR29hbHNQZXI5MCA+IEdvYWxzUGVyOTAsIGFzLmNoYXJhY3RlcihOYW1lKSwnJykpLCBtYXgub3ZlcmxhcHMgPSAxMCwgcG9pbnQucGFkZGluZyA9IDAuMSwgbnVkZ2VfeCA9IDAuMSwgbnVkZ2VfeSA9IDAsIGZvcmNlICA9IDIsIGZvcmNlX3B1bGwgPSAwLCBzaXplID0gMykgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGN1dChFeHBlY3RlZEdvYWxzUGVyOTAsIGMoLUluZiwgMC42LCBJbmYpKSkpICtnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yID0gIm9yYW5nZSIpICt4bGltKDAsMS41KSAreWxpbSgwLDEuNSkgKyBnZW9tX3RleHRfcmVwZWwoYWVzKHggPSBFeHBlY3RlZEdvYWxzUGVyOTAsIHkgPSBHb2Fsc1BlcjkwLCBsYWJlbCA9IGlmZWxzZShFeHBlY3RlZEdvYWxzUGVyOTAgPiAwLjYgJiBFeHBlY3RlZEdvYWxzUGVyOTAgPCBHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIGJveC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gLTAuMywgbnVkZ2VfeSA9IDAsIHNpemUgPSAzKSArIGxhYnMoY29sPSJ4RyBwZXIgOTAiKSArIHhsYWIoInhHIHBlciA5MCBNaW51dGVzIikgKyB5bGFiKCJHb2FscyBwZXIgOTAgTWludXRlcyIpICsgZ2d0aXRsZSgiUGxvdCBvZiBPdXRmaWVsZCBTZXJpZSBBIFBsYXllcnMgR29hbHMgcGVyIDkwIG1pbiB2cyB4RyBwZXIgOTAgbWluIikKYGBgCgoKUGxvdHRpbmcgRXhwZWN0ZWQgR29hbHMgdnMgQWN0dWFsIEdvYWwgKHBlciA5MCkgZXhjbHVkaW5nIFBlbmFsdGllcwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBzZXJpZWFfcGxheWVyX3N1bW1hcnksIGFlcyhuUHhHUGVyOTAsIE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBsYWJlbCA9IE5hbWUpKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IG5QeEdQZXI5MCwgeSA9IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBsYWJlbCA9IGlmZWxzZShuUHhHUGVyOTAgPiAwLjUgJiBuUHhHUGVyOTAgPiBOb25QZW5hbHR5R29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBwb2ludC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4zLCBudWRnZV95ID0gLTAuMiwgZm9yY2UgID0gMywgZm9yY2VfcHVsbCA9IDAsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSwgYm94LnBhZGRpbmcgPSAwLjUpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjdXQoblB4R1BlcjkwLCBjKC1JbmYsIDAuNSwgSW5mKSkpKSArZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvciA9ICJvcmFuZ2UiKSAreGxpbSgwLDEuNSkgK3lsaW0oMCwxLjUpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gblB4R1BlcjkwLCB5ID0gTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKG5QeEdQZXI5MCA+IDAuNSAmIG5QeEdQZXI5MCA8IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIG51ZGdlX3ggPSAwLjEsIG51ZGdlX3kgPSAwLjUsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSwgYm94LnBhZGRpbmcgPSAwLjUpICsgbGFicyhjb2w9Im5weEcgcGVyIDkwIikgKyB4bGFiKCJOb24tUGVuYWx0eSB4RyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiR29hbHMgcGVyIDkwIE1pbnV0ZXMiKSArIGdndGl0bGUoIlBsb3Qgb2YgT3V0ZmllbGQgU2VyaWUgQSBQbGF5ZXJzIEdvYWxzIHBlciA5MCBtaW4gdnMgblB4RyBwZXIgOTAgbWluIikKYGBgCgoKUGxvdHRpbmcgRXhwZWN0ZWQgQXNzaXN0cyB2cyBBY3R1YWwgQXNzaXN0CgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBzZXJpZWFfcGxheWVyX3N1bW1hcnksIGFlcyh4QXNzaXN0c1BlcjkwLCBBc3Npc3RzUGVyOTAsIGxhYmVsID0gTmFtZSkpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0geEFzc2lzdHNQZXI5MCwgeSA9IEFzc2lzdHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoeEFzc2lzdHNQZXI5MCA+IDAuMyAmIHhBc3Npc3RzUGVyOTAgPiBBc3Npc3RzUGVyOTAsIGFzLmNoYXJhY3RlcihOYW1lKSwnJykpLCBtYXgub3ZlcmxhcHMgPSAxMCwgcG9pbnQucGFkZGluZyA9IDAuMSwgbnVkZ2VfeCA9IDAuMiwgbnVkZ2VfeSA9MCwgZm9yY2UgID0gNSwgZm9yY2VfcHVsbCA9IDAsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSwgYm94LnBhZGRpbmcgPSAwLjUpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjdXQoeEFzc2lzdHNQZXI5MCwgYygtSW5mLCAwLjMsIEluZikpKSkgK2dlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgY29sb3IgPSAib3JhbmdlIikgK3hsaW0oMCwxKSAreWxpbSgwLDEpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0geEFzc2lzdHNQZXI5MCwgeSA9IEFzc2lzdHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoeEFzc2lzdHNQZXI5MCA+IDAuMyAmIHhBc3Npc3RzUGVyOTAgPCBBc3Npc3RzUGVyOTAsIGFzLmNoYXJhY3RlcihOYW1lKSwnJykpLCBtYXgub3ZlcmxhcHMgPSAxMCwgYm94LnBhZGRpbmcgPSAwLjUsIG51ZGdlX3ggPSAwLjI1LCBudWRnZV95ID0gMCwgZm9yY2UgID0gNSwgZm9yY2VfcHVsbCA9IDAsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSkgKyBsYWJzKGNvbD0ieEFzc2lzdHMgcGVyIDkwIikgKyB4bGFiKCJ4QXNzaXN0cyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiQXNzaXN0cyBwZXIgOTAgTWludXRlcyIpICsgZ2d0aXRsZSgiUGxvdCBvZiBPdXRmaWVsZCBTZXJpZSBBIFBsYXllcnMgQXNzaXN0cyBwZXIgOTAgbWluIHZzIHhBc3Npc3RzIHBlciA5MCBtaW4iKQpgYGAKCgpgYGB7cn0KbGFsaWdhX3BsYXllcl9zdW1tYXJ5ID0gbGFsaWdhX3BsYXllciAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoTmFtZSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShUb3RhbE1pbnV0ZXNQbGF5ZWQgPSBzdW0oTWluKSwgVG90YWxFeHBlY3RlZEdvYWxzID0gc3VtKGBFeHBlY3RlZCBHb2Fsc2ApLCBUb3RhbEdvYWxzID1zdW0oR29hbHMpLCBQZW5hbHR5R29hbHMgPSBzdW0oYFBlbmFsdHkgS2lja3MgTWFkZWApLCBUb3RhbEFzc2lzdHM9IHN1bShBc3Npc3RzKSwgVG90YWxFeHBlY3RlZEFzc2lzdHMgPSBzdW0oYEV4cGVjdGVkIEFzc2lzdGApLCBUb3RhbG5QeEcgPSBzdW0oYE5vbi1QZW5hbHR5IEV4cGVjdGVkIEdvYWxzYCkpCmxhbGlnYV9wbGF5ZXJfc3VtbWFyeSA9IGxhbGlnYV9wbGF5ZXJfc3VtbWFyeSAlPiUgZmlsdGVyKFRvdGFsTWludXRlc1BsYXllZCA+PSA5MDApCmxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiUGVyZm9ybWFuY2VHb2FsU2NvcmVkIl0gPSBsYWxpZ2FfcGxheWVyX3N1bW1hcnlbIlRvdGFsR29hbHMiXSAtIGxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxFeHBlY3RlZEdvYWxzIl0KbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJHb2Fsc1BlcjkwIl0gPSBsYWxpZ2FfcGxheWVyX3N1bW1hcnlbIlRvdGFsR29hbHMiXSooOTAvbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJFeHBlY3RlZEdvYWxzUGVyOTAiXSA9IGxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxFeHBlY3RlZEdvYWxzIl0qKDkwL2xhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiTm9uUGVuYWx0eUdvYWxzIl0gPSBsYWxpZ2FfcGxheWVyX3N1bW1hcnlbIlRvdGFsR29hbHMiXSAtIGxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiUGVuYWx0eUdvYWxzIl0KbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJOb25QZW5hbHR5R29hbHNQZXI5MCJdID0gbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJOb25QZW5hbHR5R29hbHMiXSooOTAvbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJuUHhHUGVyOTAiXSA9IGxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxuUHhHIl0qKDkwL2xhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxNaW51dGVzUGxheWVkIl0pCmxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiQXNzaXN0c1BlcjkwIl0gPSBsYWxpZ2FfcGxheWVyX3N1bW1hcnlbIlRvdGFsQXNzaXN0cyJdKig5MC9sYWxpZ2FfcGxheWVyX3N1bW1hcnlbIlRvdGFsTWludXRlc1BsYXllZCJdKQpsYWxpZ2FfcGxheWVyX3N1bW1hcnlbInhBc3Npc3RzUGVyOTAiXSA9IGxhbGlnYV9wbGF5ZXJfc3VtbWFyeVsiVG90YWxFeHBlY3RlZEFzc2lzdHMiXSooOTAvbGFsaWdhX3BsYXllcl9zdW1tYXJ5WyJUb3RhbE1pbnV0ZXNQbGF5ZWQiXSkKbGFsaWdhX3BsYXllcl9zdW1tYXJ5CgpgYGAKCgpQbG90dGluZyBFeHBlY3RlZCBHb2FscyB2cyBBY3R1YWwgR29hbCAocGVyIDkwKSBpbmNsdWRpbmcgUGVuYWx0aWVzCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBsYWxpZ2FfcGxheWVyX3N1bW1hcnksIGFlcyhFeHBlY3RlZEdvYWxzUGVyOTAsIEdvYWxzUGVyOTAsIGxhYmVsID0gTmFtZSkpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gRXhwZWN0ZWRHb2Fsc1BlcjkwLCB5ID0gR29hbHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoRXhwZWN0ZWRHb2Fsc1BlcjkwID4gMC41ICYgRXhwZWN0ZWRHb2Fsc1BlcjkwID4gR29hbHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBwb2ludC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4xLCBudWRnZV95ID0gMCwgZm9yY2UgID0gMiwgZm9yY2VfcHVsbCA9IDAsIHNpemUgPSAzKSArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY3V0KEV4cGVjdGVkR29hbHNQZXI5MCwgYygtSW5mLCAwLjUsIEluZikpKSkgK2dlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgY29sb3IgPSAib3JhbmdlIikgK3hsaW0oMCwxLjApICt5bGltKDAsMS4wKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IEV4cGVjdGVkR29hbHNQZXI5MCwgeSA9IEdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKEV4cGVjdGVkR29hbHNQZXI5MCA+IDAuNSAmIEV4cGVjdGVkR29hbHNQZXI5MCA8IEdvYWxzUGVyOTAsIGFzLmNoYXJhY3RlcihOYW1lKSwnJykpLCBtYXgub3ZlcmxhcHMgPSAxMCwgYm94LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAtMC4zLCBudWRnZV95ID0gMCwgc2l6ZSA9IDMpICsgbGFicyhjb2w9InhHIHBlciA5MCIpICsgeGxhYigieEcgcGVyIDkwIE1pbnV0ZXMiKSArIHlsYWIoIkdvYWxzIHBlciA5MCBNaW51dGVzIikgKyBnZ3RpdGxlKCJQbG90IG9mIE91dGZpZWxkIExhIExpZ2EgUGxheWVycyBHb2FscyBwZXIgOTAgbWluIHZzIHhHIHBlciA5MCBtaW4iKQpgYGAKCgpQbG90dGluZyBFeHBlY3RlZCBHb2FscyB2cyBBY3R1YWwgR29hbCAocGVyIDkwKSBleGNsdWRpbmcgUGVuYWx0aWVzCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGxhbGlnYV9wbGF5ZXJfc3VtbWFyeSwgYWVzKG5QeEdQZXI5MCwgTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gTmFtZSkpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gblB4R1BlcjkwLCB5ID0gTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKG5QeEdQZXI5MCA+IDAuNCAmIG5QeEdQZXI5MCA+IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIHBvaW50LnBhZGRpbmcgPSAwLjEsIG51ZGdlX3ggPSAwLjMsIG51ZGdlX3kgPTAsIGZvcmNlICA9IDMsIGZvcmNlX3B1bGwgPSAwLCBzaXplPTMsIGxhYmVsLnBhZGRpbmcgPSAwLjUsIGJveC5wYWRkaW5nID0gMC41KSArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY3V0KG5QeEdQZXI5MCwgYygtSW5mLCAwLjQsIEluZikpKSkgK2dlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgY29sb3IgPSAib3JhbmdlIikgK3hsaW0oMCwxKSAreWxpbSgwLDEpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0gblB4R1BlcjkwLCB5ID0gTm9uUGVuYWx0eUdvYWxzUGVyOTAsIGxhYmVsID0gaWZlbHNlKG5QeEdQZXI5MCA+IDAuNCAmIG5QeEdQZXI5MCA8IE5vblBlbmFsdHlHb2Fsc1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIG51ZGdlX3ggPSAwLjEsIG51ZGdlX3kgPSAwLCBzaXplPTMsIGxhYmVsLnBhZGRpbmcgPSAwLjUsIGJveC5wYWRkaW5nID0gMC41KSArIGxhYnMoY29sPSJucHhHIHBlciA5MCIpICsgeGxhYigiTm9uLVBlbmFsdHkgeEcgcGVyIDkwIE1pbnV0ZXMiKSArIHlsYWIoIkdvYWxzIHBlciA5MCBNaW51dGVzIikgKyBnZ3RpdGxlKCJQbG90IG9mIE91dGZpZWxkIExhIExpZ2EgUGxheWVycyBHb2FscyBwZXIgOTAgbWluIHZzIG5QeEcgcGVyIDkwIG1pbiIpCmBgYAoKClBsb3R0aW5nIEV4cGVjdGVkIEFzc2lzdHMgdnMgQWN0dWFsIEFzc2lzdAoKYGBge3J9CmdncGxvdChkYXRhID0gbGFsaWdhX3BsYXllcl9zdW1tYXJ5LCBhZXMoeEFzc2lzdHNQZXI5MCwgQXNzaXN0c1BlcjkwLCBsYWJlbCA9IE5hbWUpKSArIGdlb21fdGV4dF9yZXBlbChhZXMoeCA9IHhBc3Npc3RzUGVyOTAsIHkgPSBBc3Npc3RzUGVyOTAsIGxhYmVsID0gaWZlbHNlKHhBc3Npc3RzUGVyOTAgPiAwLjI1ICYgeEFzc2lzdHNQZXI5MCA+IEFzc2lzdHNQZXI5MCwgYXMuY2hhcmFjdGVyKE5hbWUpLCcnKSksIG1heC5vdmVybGFwcyA9IDEwLCBwb2ludC5wYWRkaW5nID0gMC4xLCBudWRnZV94ID0gMC4yLCBudWRnZV95ID0wLCBmb3JjZSAgPSA1LCBmb3JjZV9wdWxsID0gMCwgc2l6ZT0zLCBsYWJlbC5wYWRkaW5nID0gMC41LCBib3gucGFkZGluZyA9IDAuNSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGN1dCh4QXNzaXN0c1BlcjkwLCBjKC1JbmYsIDAuMjUsIEluZikpKSkgK2dlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgY29sb3IgPSAib3JhbmdlIikgK3hsaW0oMCwxKSAreWxpbSgwLDEpICsgZ2VvbV90ZXh0X3JlcGVsKGFlcyh4ID0geEFzc2lzdHNQZXI5MCwgeSA9IEFzc2lzdHNQZXI5MCwgbGFiZWwgPSBpZmVsc2UoeEFzc2lzdHNQZXI5MCA+IDAuMjUgJiB4QXNzaXN0c1BlcjkwIDwgQXNzaXN0c1BlcjkwLCBhcy5jaGFyYWN0ZXIoTmFtZSksJycpKSwgbWF4Lm92ZXJsYXBzID0gMTAsIGJveC5wYWRkaW5nID0gMC41LCBudWRnZV94ID0gMC4yNSwgbnVkZ2VfeSA9IDAuMSwgZm9yY2UgID0gNSwgZm9yY2VfcHVsbCA9IDAsIHNpemU9MywgbGFiZWwucGFkZGluZyA9IDAuNSkgKyBsYWJzKGNvbD0ieEFzc2lzdHMgcGVyIDkwIikgKyB4bGFiKCJ4QXNzaXN0cyBwZXIgOTAgTWludXRlcyIpICsgeWxhYigiQXNzaXN0cyBwZXIgOTAgTWludXRlcyIpICsgZ2d0aXRsZSgiUGxvdCBvZiBPdXRmaWVsZCBMYSBMaWdhIFBsYXllcnMgQXNzaXN0cyBwZXIgOTAgbWluIHZzIHhBc3Npc3RzIHBlciA5MCBtaW4iKQpgYGAKCmBgYHtyfQoKZ2V0X3Bhc3NfY2hhcnQ9ZnVuY3Rpb24obmFtZSkgewogIHBsYXllciA9IGVwbF9wbGF5ZXJbd2hpY2goZXBsX3BsYXllclsiTmFtZSJdID09IG5hbWUpLF0lPiUKICBzZWxlY3QoTWF0Y2h3ZWVrLCBSb3VuZCxPcHBvbmVudCwgTWluLCBgVG90YWwgUGFzc2VzIENvbXBsZXRlZGAsIGBUb3RhbCBQYXNzZXMgQXR0ZW1wdGVkYCwgYFNob3J0IFBhc3NlcyBDb21wbGV0ZWRgLCBgU2hvcnQgUGFzc2VzIEF0dGVtcHRlZGAsYE1lZGl1bSBQYXNzZXMgQ29tcGxldGVkYCwgYE1lZGl1bSBQYXNzZXMgQXR0ZW1wdGVkYCxgTG9uZyBQYXNzZXMgQ29tcGxldGVkYCxgTG9uZyBQYXNzZXMgQXR0ZW1wdGVkYCkKICBmb3IgKGkgaW4gMTozOCkgewogICAgY3Vycm13ID0gcGFzdGUoIk1hdGNod2VlayIsIHRvU3RyaW5nKGkpLCBzZXA9IiAiKQogICAgaWYgKCFhbnkocGxheWVyPT1jdXJybXcpICkgewogICAgICBuZXdfcm93ID0gZGF0YS5mcmFtZShpLCBjdXJybXcsIk5BIiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCkKICAgICAgbmFtZXMobmV3X3JvdykgPSBjKCJNYXRjaHdlZWsiLCJSb3VuZCIsICJPcHBvbmVudCIsICJNaW4iLCAiVG90YWwgUGFzc2VzIENvbXBsZXRlZCIsICJUb3RhbCBQYXNzZXMgQXR0ZW1wdGVkIiwgIlNob3J0IFBhc3NlcyBDb21wbGV0ZWQiLCAiU2hvcnQgUGFzc2VzIEF0dGVtcHRlZCIsICJNZWRpdW0gUGFzc2VzIENvbXBsZXRlZCIsICJNZWRpdW0gUGFzc2VzIEF0dGVtcHRlZCIsICJMb25nIFBhc3NlcyBDb21wbGV0ZWQiLCAiTG9uZyBQYXNzZXMgQXR0ZW1wdGVkIikKICAgICAgcGxheWVyID0gcmJpbmQocGxheWVyLCBuZXdfcm93KQogICAgfSBlbHNlIHsKICAgICAgcGxheWVyJE1hdGNod2Vla1twbGF5ZXIkUm91bmQgPT0gY3Vycm13XSA9IGkKICAgIH0KICB9CiAgcGxheWVyID0gcGxheWVyW29yZGVyKHBsYXllciRNYXRjaHdlZWspLF0KICAKICB0ZW1wX3BsYXllciA8LSBtZWx0KHBsYXllclssYygnTWF0Y2h3ZWVrJywnU2hvcnQgUGFzc2VzIEF0dGVtcHRlZCcsJ01lZGl1bSBQYXNzZXMgQXR0ZW1wdGVkJywnTG9uZyBQYXNzZXMgQXR0ZW1wdGVkJyldLGlkLnZhcnMgPSAxKQogIAogIHRpdGxlX3ZhbHVlID0gcGFzdGUobmFtZSwgIlBhc3MgQ2hhcnQiLCBzZXA9IiAiKQogIGdncGxvdCh0ZW1wX3BsYXllcixhZXMoeCA9IE1hdGNod2Vlayx5ID0gdmFsdWUpKSArIAogICAgZ2VvbV9iYXIoYWVzKGZpbGwgPSB2YXJpYWJsZSksc3RhdCA9ICJpZGVudGl0eSIscG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICBnZ3RpdGxlKHRpdGxlX3ZhbHVlKSArIAogICAgbGFicyhjb2w9IlR5cGVzIG9mIFBhc3NlcyIpCiAgCn0KCmBgYAoKCgpgYGB7cn0KZ2V0X3Bhc3NfY2hhcnQoIlRoaWFnbyBBbGPDoW50YXJhIikKYGBgCgpgYGB7cn0KCmdldF9wcmVzc3VyZV9jaGFydD1mdW5jdGlvbihuYW1lKSB7CiAgcGxheWVyID0gZXBsX3BsYXllclt3aGljaChlcGxfcGxheWVyWyJOYW1lIl0gPT0gbmFtZSksXSU+JQogIHNlbGVjdChNYXRjaHdlZWssIFJvdW5kLE9wcG9uZW50LCBNaW4sIGBOdW1iZXIgb2YgdGltZXMgYXBwbHlpbmcgcHJlc3N1cmVzIGluIERlZmVuc2l2ZSB0aGlyZGAsIGBOdW1iZXIgb2YgdGltZXMgYXBwbHlpbmcgcHJlc3N1cmVzIGluIE1pZGZpZWxkIHRoaXJkYCwgYE51bWJlciBvZiB0aW1lcyBhcHBseWluZyBwcmVzc3VyZXMgaW4gQXR0YWNraW5nIHRoaXJkYCkKICBmb3IgKGkgaW4gMTozOCkgewogICAgY3Vycm13ID0gcGFzdGUoIk1hdGNod2VlayIsIHRvU3RyaW5nKGkpLCBzZXA9IiAiKQogICAgaWYgKCFhbnkocGxheWVyPT1jdXJybXcpICkgewogICAgICBuZXdfcm93ID0gZGF0YS5mcmFtZShpLCBjdXJybXcsIk5BIiwgMCwgMCwgMCwgMCkKICAgICAgbmFtZXMobmV3X3JvdykgPSBjKCJNYXRjaHdlZWsiLCJSb3VuZCIsICJPcHBvbmVudCIsICJNaW4iLCAiTnVtYmVyIG9mIHRpbWVzIGFwcGx5aW5nIHByZXNzdXJlcyBpbiBEZWZlbnNpdmUgdGhpcmQiLCAiTnVtYmVyIG9mIHRpbWVzIGFwcGx5aW5nIHByZXNzdXJlcyBpbiBNaWRmaWVsZCB0aGlyZCIsICJOdW1iZXIgb2YgdGltZXMgYXBwbHlpbmcgcHJlc3N1cmVzIGluIEF0dGFja2luZyB0aGlyZCIpCiAgICAgIHBsYXllciA9IHJiaW5kKHBsYXllciwgbmV3X3JvdykKICAgIH0gZWxzZSB7CiAgICAgIHBsYXllciRNYXRjaHdlZWtbcGxheWVyJFJvdW5kID09IGN1cnJtd10gPSBpCiAgICB9CiAgfQogIHBsYXllciA9IHBsYXllcltvcmRlcihwbGF5ZXIkTWF0Y2h3ZWVrKSxdCiAgY29sbmFtZXMocGxheWVyKVs1XSA9ICJEZWZlbnNpdmUzcmQiCiAgY29sbmFtZXMocGxheWVyKVs2XSA9ICJNaWRmaWVsZDNyZCIKICBjb2xuYW1lcyhwbGF5ZXIpWzddID0gIkF0dGFja2luZzNyZCIKICB0ZW1wX3BsYXllciA8LSBtZWx0KHBsYXllclssYygnTWF0Y2h3ZWVrJywnRGVmZW5zaXZlM3JkJywnTWlkZmllbGQzcmQnLCdBdHRhY2tpbmczcmQnKV0saWQudmFycyA9IDEsIHZhbHVlLm5hbWUgPSAiUHJlc3N1cmVzIiwgdmFyaWFibGUubmFtZSA9ICJUeXBlcyBvZiBQcmVzc3VyZSIpCiAgdGl0bGVfdmFsdWUgPSBwYXN0ZShuYW1lLCAiUHJlc3N1cmUgQXBwbGllZCBDaGFydCIsIHNlcD0iICIpCiAgZ2dwbG90KHRlbXBfcGxheWVyLGFlcyh4ID0gTWF0Y2h3ZWVrLHkgPSBQcmVzc3VyZXMpKSArCiAgICBnZW9tX2JhcihhZXMoZmlsbCA9IGBUeXBlcyBvZiBQcmVzc3VyZWApLHN0YXQgPSAiaWRlbnRpdHkiLHBvc2l0aW9uID0gImRvZGdlIikgKwogICAgZ2d0aXRsZSh0aXRsZV92YWx1ZSkgKwogICAgeWxpbSgwLCAzMCkKICAKfQoKYGBgCgoKYGBge3J9CiMgZ2V0X3ByZXNzdXJlX2NoYXJ0KCJUaGlhZ28gQWxjw6FudGFyYSIpCmdldF9wcmVzc3VyZV9jaGFydCgiVHJlbnQgQWxleGFuZGVyLUFybm9sZCIpCmdldF9wcmVzc3VyZV9jaGFydCgiQW5kcmV3IFJvYmVydHNvbiIpCmdldF9wcmVzc3VyZV9jaGFydCgiTW9oYW1lZCBTYWxhaCIpCmdldF9wcmVzc3VyZV9jaGFydCgiU2FkaW8gTWFuw6kiKQojIGdldF9wcmVzc3VyZV9jaGFydCgiUm9iZXJ0byBGaXJtaW5vIikKIyBnZXRfcHJlc3N1cmVfY2hhcnQoIkZhYmluaG8iKQojIGdldF9wcmVzc3VyZV9jaGFydCgiR2VvcmdpbmlvIFdpam5hbGR1bSIpCiMgZ2V0X3ByZXNzdXJlX2NoYXJ0KCJCcnVubyBGZXJuYW5kZXMiKQojIGdldF9wcmVzc3VyZV9jaGFydCgiTWFyY3VzIFJhc2hmb3JkIikKIyBnZXRfcHJlc3N1cmVfY2hhcnQoIlBhdWwgUG9nYmEiKQojIGdldF9wcmVzc3VyZV9jaGFydCgiU2NvdHQgTWNUb21pbmF5IikKIyBnZXRfcHJlc3N1cmVfY2hhcnQoIkZyZWQiKQojIGdldF9wcmVzc3VyZV9jaGFydCgiRWRpbnNvbiBDYXZhbmkiKQojIGdldF9wcmVzc3VyZV9jaGFydCgixLBsa2F5IEfDvG5kb8SfYW4iKQojIGdldF9wcmVzc3VyZV9jaGFydCgiS2V2aW4gRGUgQnJ1eW5lIikKIyBnZXRfcHJlc3N1cmVfY2hhcnQoIlJpeWFkIE1haHJleiIpCiMgZ2V0X3ByZXNzdXJlX2NoYXJ0KCJQaGlsIEZvZGVuIikKIyBnZXRfcHJlc3N1cmVfY2hhcnQoIlJhaGVlbSBTdGVybGluZyIpCiMgZ2V0X3ByZXNzdXJlX2NoYXJ0KCJSb2RyaSIpCmBgYAoKCgoKCgo=